/*
  main.js - Electron 主进程入口
  - 创建主窗口与自定义标题栏区域
  - 管理多标签 BrowserView（创建/切换/关闭/布局）
  - 通过 IPC 与渲染进程通信（tabs 状态、导航、UI 尺寸）
  - 简单的“检查更新”实现：从 UPDATE_JSON_URL 拉取版本信息并比对
*/
const { app, BrowserWindow, BrowserView, ipcMain, nativeTheme, Menu, globalShortcut } = require('electron');
const path = require('path');
const fs = require('fs');
const fsPromises = fs.promises;
const dotenv = require('dotenv');
const https = require('https');
const http = require('http');
const pkg = require('./package.json');
const DouyinElectronPublisher = require('./douyin-electron-publisher');
const XiaohongshuElectronPublisher = require('./xiaohongshu-electron-publisher');


// 加载 .env：优先打包后的 resourcesPath，其次当前工作目录与源码目录
(function loadDotenv() {
  try {
    const candidates = [];
    if (process.resourcesPath) {
      candidates.push(path.join(process.resourcesPath, '.env'));
    }
    candidates.push(path.join(process.cwd(), '.env'));
    candidates.push(path.join(__dirname, '.env'));
    for (const p of candidates) {
      try {
        if (fs.existsSync(p)) {
          dotenv.config({ path: p, override: true });
          break;
        }
      } catch (_) {}
    }
  } catch (_) {}
})();

// Height of the top UI (tab bar + address bar) in the main window
let TOP_UI_HEIGHT = 84; // px

// 从 .env 读取服务地址与保护前缀
const SERVER_URL = process.env.SERVER_URL;
const PROTECTED_BASE_URL = process.env.PROTECTED_BASE_URL || SERVER_URL;

/**
 * HTTP(S) GET 并解析 JSON，5s 超时
 * @param {string} url - 请求地址
 * @returns {Promise<any>} - 解析后的 JSON
 */
function fetchJson(url) {
  return new Promise((resolve, reject) => {
    const lib = url.startsWith('https') ? https : http;
    const req = lib.get(url, (res) => {
      if (res.statusCode !== 200) {
        reject(new Error(`HTTP ${res.statusCode}`));
        res.resume();
        return;
      }
      let data = '';
      res.setEncoding('utf8');
      res.on('data', (chunk) => (data += chunk));
      res.on('end', () => {
        try {
          const json = JSON.parse(data);
          resolve(json);
        } catch (e) {
          reject(e);
        }
      });
    });
    req.on('error', reject);
    req.setTimeout(5000, () => {
      req.destroy(new Error('timeout'));
    });
  });
}

/**
 * 语义化版本简单比较（x.y.z）
 * @param {string} a
 * @param {string} b
 * @returns {number} 1:a>b, -1:a<b, 0:相等
 */
function compareVersions(a, b) {
  const pa = String(a).split('.').map(Number);
  const pb = String(b).split('.').map(Number);
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
    const x = pa[i] || 0;
    const y = pb[i] || 0;
    if (x > y) return 1;
    if (x < y) return -1;
  }
  return 0;
}

/**
 * 检查更新：从 UPDATE_JSON_URL 拉取 {version, notes} 并与当前版本比对
 * @returns {Promise<{available?: boolean, latest?: string, current?: string, notes?: string, error?: string}>}
 */
async function checkForUpdates() {
  // You can replace this URL with your own endpoint that returns { version: "x.y.z", notes?: string }
  const updateUrl = process.env.UPDATE_JSON_URL;
  try {
    const latest = await fetchJson(updateUrl);
    const latestVersion = latest.version;
    const current = pkg.version;
    const cmp = compareVersions(latestVersion, current);
    const available = cmp === 1;
    return { available, latest: latestVersion, current, notes: latest.notes || '' };
  } catch (err) {
    return { error: String(err && err.message ? err.message : err) };
  }
}

/**
 * Home URL 选择：优先本地 127.0.0.1，其次远端；支持通过环境变量 HOME_URLS 配置（逗号分隔）
 */
let HOME_CANDIDATES = [];
let selectedHomeUrl = '';

function getConfiguredHomeCandidates() {
  const envList = process.env.HOME_URLS;
  if (envList && typeof envList === 'string') {
    const arr = envList
      .split(',')
      .map(s => String(s).trim())
      .filter(Boolean);
    if (arr.length > 0) return arr;
  }
  // 默认优先本地再远端
  return [SERVER_URL];
}

/**
 * 以 HEAD 请求快速探测 URL 可达性，返回耗时（ms）。超时或失败则 reject。
 * @param {string} url
 * @param {number} timeoutMs
 * @returns {Promise<number>}
 */
function probeUrl(url, timeoutMs = 100) {
  return new Promise((resolve, reject) => {
    const lib = url.startsWith('https') ? https : http;
    const startedAt = Date.now();
    const req = lib.request(url, { method: 'HEAD' }, (res) => {
      // 任意响应都认为可达，立即结束
      res.resume();
      const elapsed = Date.now() - startedAt;
      resolve(elapsed);
      try { req.destroy(); } catch (_) {}
    });
    req.on('error', reject);
    req.setTimeout(timeoutMs, () => {
      try { req.destroy(new Error('timeout')); } catch (_) {}
    });
    req.end();
  });
}

/**
 * 挑选最快可达的 Home URL。若全都失败，则返回候选的第一个。
 * 结果会缓存到 selectedHomeUrl。
 */
async function ensureHomeUrl() {
  if (selectedHomeUrl) return selectedHomeUrl;
  HOME_CANDIDATES = getConfiguredHomeCandidates();
  // 如果只有一个候选，直接返回，避免任何探测等待
  if (HOME_CANDIDATES.length <= 1) {
    selectedHomeUrl = HOME_CANDIDATES[0] || SERVER_URL;
    return selectedHomeUrl;
  }
  try {
    const results = await Promise.all(
      HOME_CANDIDATES.map(u =>
        probeUrl(u).then(ms => ({ url: u, ms })).catch(() => ({ url: u, ms: Number.POSITIVE_INFINITY }))
      )
    );
    results.sort((a, b) => a.ms - b.ms);
    const best = results[0];
    selectedHomeUrl = best && isFinite(best.ms) ? best.url : HOME_CANDIDATES[0];
  } catch (_) {
    selectedHomeUrl = HOME_CANDIDATES[0];
  }
  return selectedHomeUrl;
}

function getHomeUrl() {
  return selectedHomeUrl || HOME_CANDIDATES[0] || SERVER_URL;
}

function isProtectedUrl(url) {
  return typeof url === 'string' && PROTECTED_BASE_URL && url.startsWith(PROTECTED_BASE_URL);
}

/**
 * 从 URL 提取统一的小写 origin 作为缓存键
 * @param {string} url
 * @returns {string}
 */
function getOriginFromUrl(url) {
  try {
    const o = new URL(String(url));
    return String(o.origin || '').toLowerCase();
  } catch (_) {
    return '';
  }
}

/**
 * 构建一个本地 data: 协议的轻量启动页，避免白屏
 * @param {string} message
 */
function buildSplashDataUrl(message = '正在加载…') {
  const html = `<!doctype html><html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
  <title>Loading</title>
  <style>
    html,body{height:100%;margin:0;background:#f7f8fa;color:#222;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}
    .wrap{display:flex;align-items:center;justify-content:center;height:100%;}
    .box{display:flex;gap:14px;align-items:center;background:#fff;border:1px solid #eee;border-radius:12px;padding:16px 20px;box-shadow:0 4px 18px rgba(0,0,0,.06)}
    .spinner{width:18px;height:18px;border:2px solid #e5e7eb;border-top-color:#3b82f6;border-radius:50%;animation:spin .8s linear infinite}
    .msg{font-size:13px;opacity:.85}
    @keyframes spin{to{transform:rotate(360deg)}}
  </style></head>
  <body><div class="wrap"><div class="box"><div class="spinner"></div><div class="msg">${message}</div></div></div></body></html>`;
  return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
}

/**
 * 构建 SERVER_URL 专用的加载页面，带有更好的动画效果
 * @param {string} serverUrl
 */
function buildServerLoadingPage(serverUrl) {
  const domain = serverUrl ? new URL(serverUrl).hostname : 'SERVER';
  const html = `<!doctype html>
<html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>正在连接${domain}...</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  html, body { height: 100%; }
  body {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    color: white;
    overflow: hidden;
  }
  
  .container {
    position: relative;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
  }
  
  .logo {
    width: 80px;
    height: 80px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 24px;
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.2);
  }
  
  .logo::before {
    content: "🌐";
    font-size: 32px;
    animation: float 3s ease-in-out infinite;
  }
  
  .loading-text {
    font-size: 24px;
    font-weight: 600;
    margin-bottom: 8px;
    text-align: center;
  }
  
  .server-info {
    font-size: 16px;
    opacity: 0.8;
    margin-bottom: 32px;
    text-align: center;
  }
  
  .progress-container {
    width: 280px;
    height: 4px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 16px;
  }
  
  .progress-bar {
    height: 100%;
    background: linear-gradient(90deg, #fff, rgba(255,255,255,0.8));
    border-radius: 2px;
    animation: loading 2s ease-in-out infinite;
  }
  
  .status-text {
    font-size: 14px;
    opacity: 0.7;
    text-align: center;
    animation: pulse 2s ease-in-out infinite;
  }
  
  .particles {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }
  
  .particle {
    position: absolute;
    width: 4px;
    height: 4px;
    background: rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    animation: particle 8s linear infinite;
  }
  
  @keyframes float {
    0%, 100% { transform: translateY(0px); }
    50% { transform: translateY(-10px); }
  }
  
  @keyframes loading {
    0% { transform: translateX(-100%); }
    50% { transform: translateX(0%); }
    100% { transform: translateX(100%); }
  }
  
  @keyframes pulse {
    0%, 100% { opacity: 0.7; }
    50% { opacity: 1; }
  }
  
  @keyframes particle {
    0% { transform: translateY(100vh) translateX(0px); opacity: 0; }
    10% { opacity: 1; }
    90% { opacity: 1; }
    100% { transform: translateY(-100px) translateX(100px); opacity: 0; }
  }
</style>
</head>
<body>
  <div class="particles" id="particles"></div>
  <div class="container">
    <div class="logo"></div>
    <div class="loading-text">正在连接服务器</div>
    <div class="server-info">${domain}</div>
    <div class="progress-container">
      <div class="progress-bar"></div>
    </div>
    <div class="status-text">正在应用登录凭证...</div>
  </div>
  
  <script>
    // 创建粒子效果
    const particles = document.getElementById('particles');
    for(let i = 0; i < 15; i++) {
      const particle = document.createElement('div');
      particle.className = 'particle';
      particle.style.left = Math.random() * 100 + '%';
      particle.style.animationDelay = Math.random() * 8 + 's';
      particle.style.animationDuration = (8 + Math.random() * 4) + 's';
      particles.appendChild(particle);
    }
  </script>
</body>
</html>`;
  return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
}

/**
 * 创建一个“首页”标签：先显示本地启动页，随后导航到最快可达的 Home URL
 * @returns {TabEntry|null}
 */
function createHomeTab() {
  // 先创建一个基本的启动页
  const tab = createTab(buildSplashDataUrl('正在打开首页…'));
  if (!tab) return tab;
  
  ensureHomeUrl().then(async (url) => {
    const wc = tab.view && tab.view.webContents;
    if (wc && !wc.isDestroyed()) {
      // 检查是否为 SERVER_URL，如果是则显示专门的加载页面
      const isServerUrl = SERVER_URL && url && url.startsWith(SERVER_URL);
      
      if (isServerUrl) {
        // 显示 SERVER_URL 专用的加载页面
        console.log('🌐 检测到 SERVER_URL，显示专用加载页面');
        await wc.loadURL(buildServerLoadingPage(url));
        
        // 等待一下让加载页面显示
        await new Promise(resolve => setTimeout(resolve, 500));
        
        // 应用 cookies (仅第一次)
        await applyServerCookiesOnce(wc);
      }
      
      // 加载实际页面
      wc.loadURL(url).catch(() => {});
    }
  }).catch(async () => {
    const wc = tab.view && tab.view.webContents;
    const fallback = getHomeUrl();
    if (wc && !wc.isDestroyed()) {
      // 检查回退页面是否为 SERVER_URL
      const isServerUrl = SERVER_URL && fallback && fallback.startsWith(SERVER_URL);
      
      if (isServerUrl) {
        // 显示 SERVER_URL 专用的加载页面
        console.log('🌐 回退页面是 SERVER_URL，显示专用加载页面');
        await wc.loadURL(buildServerLoadingPage(fallback));
        
        // 等待一下让加载页面显示
        await new Promise(resolve => setTimeout(resolve, 500));
        
        // 应用 cookies (仅第一次)
        await applyServerCookiesOnce(wc);
      }
      
      wc.loadURL(fallback).catch(() => {});
    }
  });
  return tab;
}

/**
 * Represents a single browser tab backed by a BrowserView
 */
class TabEntry {
  constructor(id, view) {
    this.id = id;
    this.view = view;
    this.title = 'New Tab';
    this.favicon = '';
    this.url = '';
    this.isLoading = false;
    this.canGoBack = false;
    this.canGoForward = false;
  }
}

/** @type {BrowserWindow | null} */
let mainWindow = null;
/** @type {TabEntry[]} */
let tabs = [];
/** @type {number | null} */
let activeTabId = null;
let nextTabId = 1;

function getActiveTab() {
  return tabs.find(t => t.id === activeTabId) || null;
}

/**
 * 创建主窗口并加载渲染端 UI；渲染完成后量测顶部高度用于 BrowserView 布局
 */
function createMainWindow() {
  mainWindow = new BrowserWindow({
    width: 1300,
    height: 800,
    titleBarStyle: 'hidden',
    trafficLightPosition: { x: 12, y: 12 },
    backgroundColor: '#ffffff',
    autoHideMenuBar: true,
    frame: process.platform === 'win32' ? false : true,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true,
      sandbox: true,
    },
  });

  mainWindow.setMenuBarVisibility(false);

  // 广播窗口最大化状态变化（供渲染端更新最大化按钮样式）
  mainWindow.on('maximize', () => {
    try { mainWindow.webContents.send('window:state', { isMaximized: true }); } catch (_) {}
  });
  mainWindow.on('unmaximize', () => {
    try { mainWindow.webContents.send('window:state', { isMaximized: false }); } catch (_) {}
  });

  mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html'));

  mainWindow.webContents.once('did-finish-load', () => {
    mainWindow.webContents.executeJavaScript(`(() => {
      const el = document.getElementById('top-ui');
      if (!el) return 90;
      const rect = el.getBoundingClientRect();
      return Math.ceil(rect.height);
    })();`).then((height) => {
      if (typeof height === 'number' && height > 0 && height < 300) {
        TOP_UI_HEIGHT = Math.ceil(height);
      }
      layoutActiveView();
      const hasAnyTab = tabs.length > 0;
      if (!hasAnyTab) {
        createHomeTab();
      }
    }).catch(() => {
      const hasAnyTab = tabs.length > 0;
      if (!hasAnyTab) {
        createHomeTab();
      }
    });
  });

  

  mainWindow.on('ready-to-show', () => {
    layoutActiveView();
  });

  mainWindow.on('resize', () => {
    layoutActiveView();
  });

  // 在 macOS 上点击关闭时仅隐藏窗口，避免销毁与重建导致的“重新加载”
  mainWindow.on('close', (e) => {
    if (process.platform === 'darwin' && !isAppQuitting) {
      e.preventDefault();
      mainWindow.hide();
    }
  });


  mainWindow.on('closed', () => {
    try {
      for (const t of tabs) {
        try {
          const wc = t && t.view && t.view.webContents;
          if (wc && !wc.isDestroyed()) wc.destroy();
        } catch (_) {}
      }
    } catch (_) {}
    tabs = [];
    activeTabId = null;
    mainWindow = null;
  });
}

/**
 * 依据窗口尺寸与顶部 UI 高度，为当前活动 BrowserView 设置可视区域
 */
function layoutActiveView() {
  if (!mainWindow) return;
  const current = getActiveTab();
  if (!current) return;
  const bounds = mainWindow.getContentBounds();
  current.view.setBounds({ x: 0, y: TOP_UI_HEIGHT, width: Math.max(0, bounds.width), height: Math.max(0, bounds.height - TOP_UI_HEIGHT) });
}

/**
 * 将指定标签页的 BrowserView 附加到窗口，并设为活动标签
 * @param {TabEntry} tab
 */
function attachView(tab) {
  if (!mainWindow) return;
  // Detach existing view if any
  const existing = getActiveTab();
  if (existing && existing.view) {
    try {
      mainWindow.removeBrowserView(existing.view);
    } catch (_) {
      // ignore
    }
  }
  mainWindow.addBrowserView(tab.view);
  layoutActiveView();
  activeTabId = tab.id;
  broadcastTabsState();
}

/**
 * 创建一个新的标签页并加载指定 URL
 * @param {string} [initialUrl]
 * @returns {TabEntry|null}
 */
function createTab(initialUrl = getHomeUrl()) {
  if (!mainWindow) return null;

  const view = new BrowserView({
    webPreferences: {
      preload: path.join(__dirname, 'view-preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
  });

  const id = nextTabId++;
  const tab = new TabEntry(id, view);
  tabs.push(tab);

  // Configure events
  const wc = view.webContents;
  wc.setBackgroundThrottling(false);


  wc.setWindowOpenHandler(({ url }) => {
    // Open target in a new tab
    createTab(url);
    return { action: 'deny' };
  });

  wc.on('did-start-loading', () => {
    tab.isLoading = true;
    updateNavState(tab);
  });

  wc.on('did-stop-loading', () => {
    tab.isLoading = false;
    updateNavState(tab);
  });

  wc.on('did-navigate', async (_, url) => {
    tab.url = url;
    updateNavState(tab);
    
    // 如果导航到 SERVER_URL，尝试应用已加载的 cookies (仅第一次)
    if (SERVER_URL && url && url.startsWith(SERVER_URL)) {
      await applyServerCookiesOnce(wc);
    }
  });


  wc.on('did-navigate-in-page', async (_, url) => {
    tab.url = url;
    updateNavState(tab);
    
    // 如果在 SERVER_URL 内导航，尝试应用 cookies (仅第一次)
    if (SERVER_URL && url && url.startsWith(SERVER_URL)) {
      await applyServerCookiesOnce(wc);
    }
  });

  wc.on('page-title-updated', (_, title) => {
    tab.title = title || 'New Tab';
    broadcastTabsState();
  });

  wc.on('page-favicon-updated', (_, favicons) => {
    if (favicons && favicons.length > 0) {
      tab.favicon = favicons[0];
      broadcastTabsState();
    }
  });

  wc.on('did-fail-load', () => {
    updateNavState(tab);
  });


  // Load initial URL with SERVER_URL loading animation support
  const loadInitialUrl = async () => {
    const isServerUrl = SERVER_URL && initialUrl && initialUrl.startsWith(SERVER_URL);
    
    if (isServerUrl) {
      // 显示 SERVER_URL 专用的加载页面
      console.log('🌐 创建 SERVER_URL 标签页，显示专用加载页面');
      await wc.loadURL(buildServerLoadingPage(initialUrl));
      
      // 等待一下让加载页面显示
      await new Promise(resolve => setTimeout(resolve, 500));
      
      // 应用 cookies (仅第一次)
      await applyServerCookiesOnce(wc);
    }
    
    // 加载实际页面
    wc.loadURL(initialUrl).catch(() => {});
  };
  
  loadInitialUrl();
  
  // 打开开发者工具并将其附加到当前网页
  wc.on('did-finish-load', () => {
    // 只在开发环境下打开开发者工具
    if (process.env.NODE_ENV === 'development') {
      // 打开开发者工具并将其停靠在右侧
      wc.openDevTools({ mode: 'right' });
    }
  });

  // Activate the new tab
  attachView(tab);

  return tab;
}

/**
 * 关闭指定标签，并自动切换到相邻标签；若全部关闭则新建一个默认标签
 * @param {number} tabId
 */
function closeTab(tabId) {
  const index = tabs.findIndex(t => t.id === tabId);
  if (index === -1) return;
  const candidate = tabs[index];
  if (isProtectedUrl(candidate && candidate.url)) {
    // 禁止关闭该服务器页面的标签
    return;
  }
  const [tab] = tabs.splice(index, 1);
  try {
    if (mainWindow) {
      try { mainWindow.removeBrowserView(tab.view); } catch (_) {}
    }
    tab.view.webContents.destroy();
  } catch (_) {}

  if (activeTabId === tabId) {
    // Activate nearest tab
    const newActive = tabs[index] || tabs[index - 1] || tabs[0] || null;
    if (newActive) {
      attachView(newActive);
    } else {
      activeTabId = null;
      broadcastTabsState();
    }
  } else {
    broadcastTabsState();
  }
}

function updateNavState(tab) {
  const wc = tab.view.webContents;
  tab.canGoBack = wc.canGoBack();
  tab.canGoForward = wc.canGoForward();
  broadcastTabsState();
}

function broadcastTabsState() {
  if (!mainWindow) return;
  const state = tabs.map(t => ({
    id: t.id,
    title: t.title || (t.url ? new URL(t.url).hostname : 'New Tab'),
    favicon: t.favicon || '',
    url: t.url || '',
    isLoading: t.isLoading,
    isActive: t.id === activeTabId,
    canGoBack: t.canGoBack,
    canGoForward: t.canGoForward,
  }));
  mainWindow.webContents.send('tabs:state', state);
}

/**
 * 向主窗口与所有标签页广播 cookies 相关事件
 * @param {string} channel
 * @param {any} payload
 */
function broadcastCookiesEvent(channel, payload) {
  try {
    if (mainWindow && !mainWindow.isDestroyed()) {
      mainWindow.webContents.send(channel, payload);
    }
  } catch (_) {}
  try {
    for (const t of tabs) {
      try {
        const wc = t && t.view && t.view.webContents;
        if (wc && !wc.isDestroyed()) wc.send(channel, payload);
      } catch (_) {}
    }
  } catch (_) {}
}




/**
 * 注册所有 IPC 通道（tabs、导航、UI 尺寸同步、检查更新）
 */
function setupIpcHandlers() {
  ipcMain.on('ui:setTopHeight', (_evt, height) => {
    if (typeof height === 'number' && height > 0 && height < 300) {
      TOP_UI_HEIGHT = Math.round(height);
      layoutActiveView();
    }
  });
  ipcMain.handle('tabs:getState', () => {
    return tabs.map(t => ({
      id: t.id,
      title: t.title || (t.url ? new URL(t.url).hostname : 'New Tab'),
      favicon: t.favicon || '',
      url: t.url || '',
      isLoading: t.isLoading,
      isActive: t.id === activeTabId,
      canGoBack: t.canGoBack,
      canGoForward: t.canGoForward,
    }));
  });

  // 窗口控制（供 Windows 自绘按钮调用）
  ipcMain.on('window:minimize', () => {
    try { if (mainWindow && !mainWindow.isDestroyed()) mainWindow.minimize(); } catch (_) {}
  });
  ipcMain.on('window:toggleMaximize', () => {
    try {
      if (!mainWindow || mainWindow.isDestroyed()) return;
      if (mainWindow.isMaximized()) mainWindow.unmaximize(); else mainWindow.maximize();
    } catch (_) {}
  });
  ipcMain.on('window:close', () => {
    try { if (mainWindow && !mainWindow.isDestroyed()) mainWindow.close(); } catch (_) {}
  });
  ipcMain.handle('window:isMaximized', () => {
    try { return !!(mainWindow && !mainWindow.isDestroyed() && mainWindow.isMaximized()); } catch (_) { return false; }
  });

  ipcMain.on('tab:create', (_evt, url) => {
    if (url && typeof url === 'string' && url.trim()) {
      createTab(url);
    } else {
      createHomeTab();
    }
  });

  ipcMain.on('tab:switch', (_evt, tabId) => {
    const tab = tabs.find(t => t.id === tabId);
    if (tab) attachView(tab);
  });

  ipcMain.on('tab:close', (_evt, tabId) => {
    closeTab(tabId);
  });

  ipcMain.on('tab:reload', () => {
    const current = getActiveTab();
    const wc = current && current.view && current.view.webContents;
    if (wc && !wc.isDestroyed()) wc.reload();
  });

  ipcMain.on('tab:goBack', () => {
    const current = getActiveTab();
    const wc = current && current.view && current.view.webContents;
    if (wc && !wc.isDestroyed() && wc.canGoBack()) {
      wc.goBack();
    }
  });

  ipcMain.on('tab:goForward', () => {
    const current = getActiveTab();
    const wc = current && current.view && current.view.webContents;
    if (wc && !wc.isDestroyed() && wc.canGoForward()) {
      wc.goForward();
    }
  });

  ipcMain.on('tab:navigate', async (_evt, url) => {
    // If user typed a bare word, treat as search query
    const finalUrl = normalizeToUrl(url);
    if (!finalUrl) return;

    const current = getActiveTab();
    if (!current) {
      createTab(finalUrl);
      return;
    }

    const wc = current.view && current.view.webContents;
    if (wc && !wc.isDestroyed()) {
      // 检查是否导航到 SERVER_URL
      const isServerUrl = SERVER_URL && finalUrl && finalUrl.startsWith(SERVER_URL);
      
      if (isServerUrl) {
        // 显示 SERVER_URL 专用的加载页面
        console.log('🌐 手动导航到 SERVER_URL，显示专用加载页面');
        await wc.loadURL(buildServerLoadingPage(finalUrl));
        
        // 等待一下让加载页面显示
        await new Promise(resolve => setTimeout(resolve, 500));
        
        // 应用 cookies (仅第一次)
        await applyServerCookiesOnce(wc);
      }
      
      // 加载实际页面
      wc.loadURL(finalUrl).catch(() => {});
    }
  });

  // IPC: 获取cookies
  ipcMain.handle('tab:getCookies', async () => {
    try {
      const current = getActiveTab();
      const wc = current && current.view && current.view.webContents;
      if (!wc || wc.isDestroyed()) return [];
      const currentUrl = wc.getURL();
      if (typeof currentUrl !== 'string' || !/^https?:\/\//i.test(currentUrl)) {
        return [];
      }
      const cookies = await wc.session.cookies.get({ url: currentUrl });
      const origin = getOriginFromUrl(currentUrl);
      if (origin) {
        cookiesCacheByOrigin[origin] = Array.isArray(cookies) ? cookies : [];
        broadcastCookiesEvent('cookies:updated', { origin, count: (cookies && cookies.length) || 0 });
      }
      console.log(JSON.stringify(cookies))
      return Array.isArray(cookies) ? cookies : [];
    } catch (_) {
      return [];
    }
  })

  ipcMain.handle('app:checkForUpdates', async () => {
    const result = await checkForUpdates();
    if (result.error) {
      mainWindow && mainWindow.webContents.send('app:updateError', result.error);
      return { available: false, current: pkg.version };
    }
    if (result.available) {
      mainWindow && mainWindow.webContents.send('app:updateAvailable', result);
    } else {
      mainWindow && mainWindow.webContents.send('app:updateNotAvailable', result);
    }
    return result;
  });

  // 读取应用配置供渲染进程使用
  ipcMain.handle('app:getConfig', () => {
    return {
      serverUrl: SERVER_URL,
      protectedBaseUrl: PROTECTED_BASE_URL,
    };
  });

  // Cookies cache IPC（按 origin 存储）
  ipcMain.handle('cookies:getCached', () => {
    try {
      const current = getActiveTab();
      const wc = current && current.view && current.view.webContents;
      const url = wc && !wc.isDestroyed() ? wc.getURL() : '';
      const origin = getOriginFromUrl(url);
      return (origin && cookiesCacheByOrigin[origin]) || [];
    } catch (_) {
      return [];
    }
  });

  ipcMain.handle('cookies:setCached', (_evt, cookies) => {
    try {
      const current = getActiveTab();
      const wc = current && current.view && current.view.webContents;
      const url = wc && !wc.isDestroyed() ? wc.getURL() : '';
      const origin = getOriginFromUrl(url);
      if (origin) {
        cookiesCacheByOrigin[origin] = Array.isArray(cookies) ? cookies : [];
        broadcastCookiesEvent('cookies:updated', { origin, count: (cookies && cookies.length) || 0 });
      }
      return true;
    } catch (_) {
      return false;
    }
  });

  ipcMain.handle('cookies:getCachedFor', (_evt, urlOrOrigin) => {
    const origin = getOriginFromUrl(String(urlOrOrigin || '')) || String(urlOrOrigin || '').toLowerCase();
    return (origin && cookiesCacheByOrigin[origin]) || [];
  });

  ipcMain.handle('cookies:setCachedFor', (_evt, urlOrOrigin, cookies) => {
    const origin = getOriginFromUrl(String(urlOrOrigin || '')) || String(urlOrOrigin || '').toLowerCase();
    if (origin) {
      cookiesCacheByOrigin[origin] = Array.isArray(cookies) ? cookies : [];
      broadcastCookiesEvent('cookies:updated', { origin, count: (cookies && cookies.length) || 0 });
      return true;
    }
    return false;
  });

  ipcMain.handle('cookies:getAllCached', () => {
    return cookiesCacheByOrigin;
  });

  // 添加网络请求处理器，解决跨域问题
  ipcMain.handle('network:fetch', async (event, url, options = {}) => {
    const { net } = require('electron');
    try {
      const request = net.request({
        method: options.method || 'GET',
        url: url,
        headers: options.headers || {}
      });

      return new Promise((resolve, reject) => {
        let responseData = Buffer.alloc(0);
        
        request.on('response', (response) => {
          response.on('data', (chunk) => {
            responseData = Buffer.concat([responseData, chunk]);
          });
          
          response.on('end', () => {
            const textData = responseData.toString('utf8');
            
            resolve({
              ok: response.statusCode >= 200 && response.statusCode < 300,
              status: response.statusCode,
              statusText: response.statusMessage,
              headers: response.headers,
              data: responseData.toString('base64'), // 将二进制数据转为base64字符串
              text: textData, // 直接返回文本数据
              contentLength: responseData.length
            });
          });
        });

        request.on('error', (error) => {
          reject(error);
        });

        if (options.body) {
          request.write(options.body);
        }
        
        request.end();
      });
    } catch (error) {
      throw error;
    }
  });

  // 🍪 Cookie 管理 IPC 处理器
  ipcMain.handle('clear-server-cookies', async (event) => {
    try {
      const webContents = event.sender;
      const currentUrl = webContents.getURL();
      
      console.log('🗑️ 收到清除 SERVER_URL cookies 的请求');
      
      if (!SERVER_URL) {
        console.warn('⚠️ SERVER_URL 未配置');
        return { success: false, message: 'SERVER_URL 未配置' };
      }
      
      // 获取当前的 cookies
      const currentCookies = await webContents.session.cookies.get({ url: SERVER_URL });
      console.log(`📊 当前有 ${currentCookies.length} 个 SERVER_URL cookies`);
      
      // 删除所有相关的 cookies
      for (const cookie of currentCookies) {
        await webContents.session.cookies.remove(SERVER_URL, cookie.name);
        console.log(`🗑️ 删除 cookie: ${cookie.name}`);
      }
      
      // 更新内存中的 cookies
      loadedServerCookies = [];
      
      // 重置该 webContents 的应用状态，以便下次可以重新应用（如果有新的cookies）
      appliedCookiesMap.delete(webContents.id);
      
      // 更新保存的 cookies 文件
      const cookiesData = {
        url: SERVER_URL,
        cookies: [],
        savedAt: new Date().toISOString()
      };
      
      await fsPromises.writeFile(getCookiesFilePath(), JSON.stringify(cookiesData, null, 2), 'utf8');
      
      console.log('✅ 成功清除所有 SERVER_URL cookies');
      
      return { 
        success: true, 
        message: `成功删除 ${currentCookies.length} 个 cookies`,
        deletedCount: currentCookies.length 
      };
      
    } catch (error) {
      console.error('❌ 清除 SERVER_URL cookies 失败:', error);
      return { 
        success: false, 
        message: `清除失败: ${error.message}` 
      };
    }
  });

  // 获取当前页面的 cookies（调试用）
  ipcMain.handle('get-current-cookies', async (event) => {
    try {
      const webContents = event.sender;
      const currentUrl = webContents.getURL();
      
      if (!currentUrl) {
        return { success: false, message: '无法获取当前页面URL' };
      }
      
      const cookies = await webContents.session.cookies.get({ url: currentUrl });
      
      console.log(`📊 当前页面 ${currentUrl} 有 ${cookies.length} 个 cookies`);
      
      return {
        success: true,
        url: currentUrl,
        cookies: cookies.map(cookie => ({
          name: cookie.name,
          value: cookie.value,
          domain: cookie.domain,
          path: cookie.path,
          expires: cookie.expirationDate ? new Date(cookie.expirationDate * 1000).toISOString() : 'Session'
        })),
        count: cookies.length
      };
      
    } catch (error) {
      console.error('❌ 获取当前页面 cookies 失败:', error);
      return { 
        success: false, 
        message: `获取失败: ${error.message}` 
      };
    }
  });

}

/**
 * 将用户输入规范化为 URL：保留 http/https；域名自动补 https；否则按关键字搜索
 * @param {string} input
 * @returns {string}
 */
function normalizeToUrl(input) {
  if (!input) return '';
  const trimmed = String(input).trim();
  if (!trimmed) return '';

  // If already seems like a URL with scheme
  if (/^https?:\/\//i.test(trimmed)) return trimmed;

  // If it looks like a domain
  if (/^[\w.-]+\.[A-Za-z]{2,}(?:\/.*)?$/.test(trimmed)) {
    return `https://${trimmed}`;
  }

  // Otherwise, treat as a search query (Baidu)
  const q = encodeURIComponent(trimmed);
  return `https://www.baidu.com/s?wd=${q}`;
}

let isAppQuitting = false;
let cookiesCacheByOrigin = Object.create(null);

// SERVER_URL cookies 管理
function getCookiesFilePath() {
  return !app.isPackaged 
    ? path.join(__dirname, 'dev-server-cookies.json')
    : path.join(app.getPath('userData'), 'server-cookies.json');
}

/**
 * 保存 SERVER_URL 的 cookies 到文件
 */
async function saveServerCookies() {
  if (!SERVER_URL) return;
  
  try {
    // 获取所有标签页中 SERVER_URL 的 cookies
    let allServerCookies = [];
    
    for (const tab of tabs) {
      try {
        const wc = tab.view && tab.view.webContents;
        if (wc && !wc.isDestroyed()) {
          const url = wc.getURL();
          if (url && url.startsWith(SERVER_URL)) {
            const cookies = await wc.session.cookies.get({ url: SERVER_URL });
            if (cookies.length > 0) {
              allServerCookies = cookies;
              break; // 找到第一个有效的就够了
            }
          }
        }
      } catch (_) {}
    }
    
    console.log(`🔍 找到 ${allServerCookies.length} 个 SERVER_URL cookies`);
    
    const cookiesData = {
      url: SERVER_URL,
      cookies: allServerCookies,
      savedAt: new Date().toISOString()
    };
    
    await fsPromises.writeFile(getCookiesFilePath(), JSON.stringify(cookiesData, null, 2), 'utf8');
    console.log(`✅ 已保存 ${allServerCookies.length} 个 SERVER_URL cookies`);
  } catch (error) {
    console.error('❌ 保存 SERVER_URL cookies 失败:', error);
  }
}

/**
 * 从文件加载 SERVER_URL 的 cookies
 */
async function loadServerCookies() {
  if (!SERVER_URL) return [];
  
  try {
    const filePath = getCookiesFilePath();
    if (fs.existsSync(filePath)) {
      const data = await fsPromises.readFile(filePath, 'utf8');
      const cookiesData = JSON.parse(data);
      
      if (cookiesData.url === SERVER_URL && cookiesData.cookies) {
        console.log(`✅ 加载了 ${cookiesData.cookies.length} 个 SERVER_URL cookies`);
        return cookiesData.cookies;
      }
    }
  } catch (error) {
    console.error('❌ 加载 SERVER_URL cookies 失败:', error);
  }
  
  return [];
}

/**
 * 为指定的 webContents 应用 SERVER_URL cookies
 */
async function applyServerCookies(webContents, savedCookies) {
  if (!SERVER_URL || !webContents || webContents.isDestroyed() || !savedCookies || savedCookies.length === 0) {
    return;
  }
  
  try {
    for (const cookie of savedCookies) {
      try {
        await webContents.session.cookies.set({
          url: SERVER_URL,
          name: cookie.name,
          value: cookie.value,
          domain: cookie.domain,
          path: cookie.path || '/',
          secure: cookie.secure || false,
          httpOnly: cookie.httpOnly || false,
          expirationDate: cookie.expirationDate,
          sameSite: cookie.sameSite || 'lax'
        });
      } catch (_) {}
    }
    console.log(`✅ 已应用 ${savedCookies.length} 个 SERVER_URL cookies`);
  } catch (error) {
    console.error('❌ 应用 SERVER_URL cookies 失败:', error);
  }
}

/**
 * 只在第一次访问时应用 SERVER_URL cookies
 */
async function applyServerCookiesOnce(webContents) {
  const webContentsId = webContents.id;
  
  // 如果这个 webContents 已经应用过 cookies，则跳过
  if (appliedCookiesMap.has(webContentsId)) {
    console.log(`🔄 webContents ${webContentsId} 已经应用过 SERVER_URL cookies，跳过`);
    return false;
  }
  
  // 如果有保存的 cookies，则应用
  if (loadedServerCookies.length > 0) {
    console.log(`🔑 webContents ${webContentsId} 首次应用 SERVER_URL cookies`);
    await applyServerCookies(webContents, loadedServerCookies);
    appliedCookiesMap.set(webContentsId, true);
    
    // 当 webContents 销毁时，清理映射
    webContents.once('destroyed', () => {
      appliedCookiesMap.delete(webContentsId);
      console.log(`🧹 清理 webContents ${webContentsId} 的 cookie 应用记录`);
    });
    
    return true;
  }
  
  return false;
}
// 🎯 存储抖音发布模块的引用
let douyinPublisher = null;
let xiaohongshuPublisher = null;

// 存储加载的 cookies，供后续使用
let loadedServerCookies = [];
// 为每个 webContents 单独跟踪是否已应用过 cookies
const appliedCookiesMap = new Map();

app.whenReady().then(async () => {
  createMainWindow();
  setupIpcHandlers();
  
  // 启动时加载 SERVER_URL cookies
  loadedServerCookies = await loadServerCookies();


  // 🎯 新增：初始化抖音发布模块
  douyinPublisher = new DouyinElectronPublisher({
    mainWindow: mainWindow,
    autoInitDB: true,
    autoRegisterIPC: true,
    headless: true  // 🎯 添加这一行启用无头模式
  });

  // 新增: 初始化小红书发布模块
  xiaohongshuPublisher = new XiaohongshuElectronPublisher({
    mainWindow: mainWindow,
    autoInitDB: true,        // 这个设置为true就会自动初始化
    autoRegisterIPC: true,   // 自动注册IPC
    headless: true
  });
  
  
  // 创建包含完整编辑功能的菜单
  const template = [
    {
      label: '粽子智推',
      submenu: [
        { label: '关于', role: 'about' },
        { label: '退出', role: 'quit' }
      ]
    },
    {
      label: '编辑',
      submenu: [
        { label: '撤销', role: 'undo' },
        { label: '重做', role: 'redo' },
        { type: 'separator' },
        { label: '剪切', role: 'cut' },
        { label: '复制', role: 'copy' },
        { label: '粘贴', role: 'paste' },
        { label: '粘贴并匹配样式', role: 'pasteandmatchstyle' },
        { label: '删除', role: 'delete' },
        { label: '全选', role: 'selectall' },
      ]
    },
    {
      label: '视图',
      submenu: [
        { label: '重新加载', role: 'reload' },
        { label: '强制重新加载', role: 'forcereload' },
        { type: 'separator' },
        { label: '实际大小', role: 'resetzoom' },
        { label: '放大', role: 'zoomin' },
        { label: '缩小', role: 'zoomout' },
        { label: '切换全屏', role: 'togglefullscreen' }
      ]
    },
    {
      label: '窗口',
      submenu: [
        { label: '最小化', role: 'minimize' },
        { label: '关闭', role: 'close' }
      ]
    }
  ];
  
  // macOS 特殊处理
  if (process.platform === 'darwin') {
    template[0].submenu.unshift(
      { label: '隐藏粽子智推', role: 'hide' },
      { label: '隐藏其他', role: 'hideothers' },
      { label: '显示全部', role: 'unhide' },
      { type: 'separator' }
    );
    
    // macOS 窗口菜单
    template[3].submenu = [
      { label: '关闭', role: 'close' },
      { label: '最小化', role: 'minimize' },
      { label: '缩放', role: 'zoom' },
      { label: '前置全部窗口', role: 'front' }
    ];
  }
  
  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);


// 记录是否是用户选择退出，用于区分"关闭窗口"与"退出应用"
  app.on('before-quit', async () => { 
    console.log('应用退出中...')
    isAppQuitting = true; 
    
    // 保存 SERVER_URL cookies
    console.log('💾 正在保存 SERVER_URL cookies...');
    await saveServerCookies();
    
    // 取消注册所有快捷键
    globalShortcut.unregisterAll();

    // 🎯 新增：清理抖音发布模块
    if (douyinPublisher) {
      await douyinPublisher.close();
    }

    // 清理小红书发布模块
    if (xiaohongshuPublisher) {
      await xiaohongshuPublisher.close();
    }
  });

  app.on('activate', function () {
    if (mainWindow) {
      mainWindow.show();
    } else {
      createMainWindow();
    }
  });
});



app.on('window-all-closed', function () {
  // 在macOS上，除非用户使用Cmd+Q明确退出，
  // 否则应用程序和菜单栏将保持活动状态
  if (process.platform !== 'darwin') {
    app.quit();
  }
});